#ifndef _PROCESS_TABLE
#define _PROCESS_TABLE
#include "bitmap.h"
#include "system.h"
#include "thread.h"
#include "addrspace.h"
#include "synch.h"
#include "syscall.h"


void Kernel_Thread_Func(unsigned int funcVAddr);
void Kernel_Process_Func(int);


int copyin(unsigned int vaddr, int len, char *buf);
int copyout(unsigned int vaddr, int len, char *buf);

class ProcessEntry
{
	friend class ProcessTable;
private:
	SpaceId _processID;
	char* _fileName;
	AddrSpace* _addressSpace;

	SpaceId _childProcessTable[MaxProcess];
	BitMap* _childProcessBitMap;
	Lock* _childProcessBitMapLock;
	int _numOfChildProcesses;
	SpaceId _parentProcessId;
	bool _waitingToFinish;
	Lock* _processLock;
	Condition* _processCV;

	int _numOfChildThreads;
	Thread* _threadTable[MaxThreadsPerProcess];
	BitMap* _threadBitMap;
	Lock* _threadBitMapLock;
	Lock* _threadTableLock[MaxThreadsPerProcess];
	Lock* _numOfThreadsLock;
	Lock* _currentProcessLock;
	int StackStartPage(int processID, int threadID, int numOfPages);
	void ReleaseResources();
	void StartProcess();
	void Initialize();
public:
	ProcessEntry(int processID, char* fileName, SpaceId parentProcessId);
	~ProcessEntry();
	int Fork(char* threadName, unsigned int funcVAddr);
	int getProcessID();
	char* getFileName();
	AddrSpace* getAddressSpace();
	void SetAddressSpace(AddrSpace* newAddrSpace);
	Thread* getThread(int threadID);
	void Exit(int threadID);
};

class ProcessTable
{
private:
	ProcessEntry* _processes[MaxProcess];
	BitMap* _processBitMap;
	BitMap* _physicalMemoryBitMap;
	Lock* _processLock[MaxProcess];
	Lock* _processBitMapLock;
	Lock* _physicalMemoryBitMapLock;
	Lock* _memoryLock;
	void ReleaseResources();
	void Initialize();
public:
	ProcessTable(void);
	~ProcessTable();
	int Exec(char* fileName, bool);
	int getAvailablePhysicalPage();
	ProcessEntry* getProcess(int pid);

};

extern ProcessTable processTable;

#endif
